#pragma once

#include <iostream>
#include <sys/epoll.h>
#include "Log.hpp"
#include "Common.hpp"

using namespace LogModule;
namespace EpollModule
{
    //分层中的最底层,具体执行任务的
    class Epoll
    {
    public:
        Epoll() : _epfd(-1)
        {
        }
        void Init()
        {
            _epfd = epoll_create(1); // 这里的参数并无实际意义,填一个正整数即可(1,64,256)
            if (_epfd < 0)
            {
                LOG(Loglevel::FATAL) << "epoll_create filed";
                Die(EPOLLCREATE_ERROR);
            }
        }
        int Wait(struct epoll_event revs[], int num, int timeout) // 输出就绪的fd和events
        {
            // 第二个参数为输出参数，用于存储就绪的事件信息,第三个参数决定Wait返回的n的最大值,timeout决定等待方式
            int n = epoll_wait(_epfd, revs, num, timeout);
            if (n < 0)
            {
                LOG(Loglevel::WARING) << "epoll_wait filed";
            }
            return n;
        }
        void Ctrl(int sockfd, uint32_t events, int flags)
        {
            struct epoll_event ev;
            ev.events = events;
            ev.data.fd = sockfd;                          // 这里的sockfd是用户自己设置的数据,可以不设置
            int n = epoll_ctl(_epfd, flags, sockfd, &ev); // 这里的sockfd是告诉内核要操作哪个sockfd,不能少
            if (n < 0)
            {
                LOG(Loglevel::WARING) << "epoll_ctl filed";
            }
        }
        // 向指定sockfd添加事件
        void Add(int sockfd, uint32_t events)
        {
            Ctrl(sockfd, events, EPOLL_CTL_ADD);
        }
        // 修改指定sockfd的事件
        void Update(int sockfd, uint32_t events)
        {
            Ctrl(sockfd, events, EPOLL_CTL_MOD);
        }
        // 删除指定sockfd的事件
        void Del(int sockfd)
        {
            // 这里EPOLL_CTL_DEL已将sockfd对应的事件全部移除,最后一个参数填什么都无所谓,直接设置为nullptr
            int n = epoll_ctl(_epfd, EPOLL_CTL_DEL, sockfd, nullptr);
            if (n < 0)
            {
                LOG(Loglevel::WARING) << "epoll_ctl filed";
            }
        }
        ~Epoll()
        {
            if (_epfd != -1)
            {
                close(_epfd);
            }
        }

    private:
        int _epfd;
    };
}